﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using C1.Phone;
using C1.Phone.FlexGrid;

using Microsoft.Phone.Shell;
using Microsoft.Phone.Controls;

namespace ControlExplorer.Controls.FlexGrid
{
    public partial class SortingFiltering
        : UserControl, IExposeApplicationBarItems
    {
        ApplicationBarIconButton btnFilter = new ApplicationBarIconButton(new Uri("/Resources/AppBar/filter.png", UriKind.Relative));
        ApplicationBarIconButton btnFilterClear = new ApplicationBarIconButton(new Uri("/Resources/AppBar/filter_clear.png", UriKind.Relative));
        ApplicationBarIconButton btnSortClear = new ApplicationBarIconButton(new Uri("/Resources/AppBar/sort_clear.png", UriKind.Relative));
        ApplicationBarMenuItem btnToggleMultipleSort = new ApplicationBarMenuItem();

        public SortingFiltering()
        {
            InitializeComponent();

            btnFilter.Text = "filter";
            btnFilter.Click += btnFilter_Click;

            btnFilterClear.Text = "clear filter";
            btnFilterClear.Click += btnFilterClear_Click;

            btnSortClear.Text = "clear sort";
            btnSortClear.Click += btnSort_Click;

            btnToggleMultipleSort.Text = "enable multiple sort";
            btnToggleMultipleSort.Click += btnToggleMultipleSort_Click;
            flexgrid.AllowSorting = false; // we'll do it ourselves

            flexgrid.ItemsSource = Person.Generate(100);
            flexgrid.Tap += flexgrid_Tap;

            filterPopup.IsOpenChanged += filterPopup_IsOpenChanged;
            UpdateButtons();

            Loaded += SortingFiltering_Loaded;
        }

        void SortingFiltering_Loaded(object sender, RoutedEventArgs e)
        {
            flexgrid.AutoSizeColumns(0, flexgrid.Columns.Count, 30);
        }

        private void UpdateButtons() 
        {
            btnSortClear.IsEnabled = (flexgrid.CollectionView.SortDescriptions.Count > 0);
            btnFilterClear.IsEnabled = (flexgrid.CollectionView.Filter != null);
        }

        #region Sort

        bool _allowMultipleSort = false;
        void btnToggleMultipleSort_Click(object sender, EventArgs e)
        {
            _allowMultipleSort = !_allowMultipleSort;

            if (_allowMultipleSort)
            {
                btnToggleMultipleSort.Text = "disable multiple sort";
            }
            else
            {
                btnToggleMultipleSort.Text = "enable multiple sort";
            }
        }

        void flexgrid_Tap(object sender, GestureEventArgs e)
        {
            // detect tap and sort only if a column header was tapped
            var testInfo = flexgrid.HitTest(e);
            if (testInfo.CellType == CellType.ColumnHeader)
            {
                // get current column header property name
                SortGrid(flexgrid.Columns[testInfo.Column].BoundPropertyName);
            }
        }

        void btnSort_Click(object sender, EventArgs e)
        {
            flexgrid.CollectionView.SortDescriptions.Clear();
            UpdateButtons();
        }

        void SortGrid(string propertyName)
        {
            // If we have a sort description with the current property path, then we remove it from the collection and
            // add a new one with the opposite sort direction (if we tap a column header twice, the sort direction changes).
            // If we don´t have a sort description with the current property path, then we add it with ascending sort direction.
            var sortDescriptions = flexgrid.CollectionView.SortDescriptions;

            using (flexgrid.CollectionView.DeferRefresh())
            {
                var sortDescription = sortDescriptions.FirstOrDefault(sd => sd.PropertyName.Equals(propertyName));

                // if multiple selection is disabled, we always clear the collection
                if (!_allowMultipleSort)
                {
                    sortDescriptions.Clear();
                }

                if (string.IsNullOrEmpty(sortDescription.PropertyName))
                {
                    sortDescription.PropertyName = propertyName;
                    sortDescription.Direction = ListSortDirection.Ascending;
                    sortDescriptions.Add(sortDescription);
                }
                else
                {
                    sortDescriptions.Remove(sortDescription);
                    sortDescriptions.Add(new SortDescription(propertyName, sortDescription.Direction == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending));
                }
            }

            UpdateButtons();
        }

        #endregion

        #region Filter

        void filterPopup_IsOpenChanged(object sender, PropertyChangedEventArgs<bool> e)
        {
            // when popup is closed...
            if (false == e.NewValue)
            {
                // BUG workaround: it's being thrown before the transition takes place.
                var page = C1.Phone.Extensions.FindParent<PhoneApplicationPage>(this);
                Dispatcher.BeginInvoke(() =>
                {
                    Dispatcher.BeginInvoke(() =>
                    {
                        if (page != null) page.ApplicationBar.IsVisible = true;
                        flexgrid.Visibility = System.Windows.Visibility.Visible;
                        UpdateButtons();
                    });
                });
            }            
        }

        void btnFilterClear_Click(object sender, EventArgs e)
        {
            flexgrid.CollectionView.Filter = null;
            UpdateButtons();
        }

        void btnFilter_Click(object sender, EventArgs e)
        {
            if (filterPopup.Content == null)
            {
                filterPopup.Content = new FlexGridFilter(flexgrid, filterPopup);
            }
            var page = C1.Phone.Extensions.FindParent<PhoneApplicationPage>(this);
            if (page != null) page.ApplicationBar.IsVisible = false;

            flexgrid.Visibility = System.Windows.Visibility.Collapsed;
            filterPopup.IsOpen = true;
        }

        #endregion

        public IEnumerable<Microsoft.Phone.Shell.IApplicationBarMenuItem> ApplicationBarItems
        {
            get
            {
                yield return btnSortClear;
                
                yield return btnFilter;
                yield return btnFilterClear;

                yield return btnToggleMultipleSort;
            }
        }
    }
}
